import {
    chat_metadata,
    substituteParams,
    this_chid,
    // eventSource,
    // event_types,
    // saveSettingsDebounced,
    // animation_duration,
} from '../lib/script.js';
import { 
  extension_settings, 
  // saveMetadataDebounced 
} from './extensions.js';
// import { selected_group } from './group-chats.js';
import { getCharaFilename, delay } from './utils.js';
import { power_user } from './power-user.js';

const extensionName = 'cfg';
const defaultSettings = {
    global: {
        'guidance_scale': 1,
        'negative_prompt': '',
    },
    chara: [],
};
// const settingType = {
//     guidance_scale: 0,
//     negative_prompt: 1,
//     positive_prompt: 2,
// };

// // Used for character and chat CFG values
// function updateSettings() {
//     saveSettingsDebounced();
//     loadSettings();
// }

// function setCharCfg(tempValue, setting) {
//     const avatarName = getCharaFilename();

//     // Assign temp object
//     let tempCharaCfg = {
//         name: avatarName,
//     };

//     switch(setting) {
//         case settingType.guidance_scale:
//             tempCharaCfg['guidance_scale'] = Number(tempValue);
//             break;
//         case settingType.negative_prompt:
//             tempCharaCfg['negative_prompt'] = tempValue;
//             break;
//         case settingType.positive_prompt:
//             tempCharaCfg['positive_prompt'] = tempValue;
//             break;
//         default:
//             return false;
//     }

//     let existingCharaCfgIndex;
//     let existingCharaCfg;

//     if (extension_settings.cfg.chara) {
//         existingCharaCfgIndex = extension_settings.cfg.chara.findIndex((e) => e.name === avatarName);
//         existingCharaCfg = extension_settings.cfg.chara[existingCharaCfgIndex];
//     }

//     if (extension_settings.cfg.chara && existingCharaCfg) {
//         const tempAssign = Object.assign(existingCharaCfg, tempCharaCfg);

//         // If both values are default, remove the entry
//         if (!existingCharaCfg.useChara &&
//             (tempAssign.guidance_scale ?? 1.00) === 1.00 &&
//             (tempAssign.negative_prompt?.length ?? 0) === 0 &&
//             (tempAssign.positive_prompt?.length ?? 0) === 0)
//         {
//             extension_settings.cfg.chara.splice(existingCharaCfgIndex, 1);
//         }
//     } else if (avatarName && tempValue.length > 0) {
//         if (!extension_settings.cfg.chara) {
//             extension_settings.cfg.chara = [];
//         }

//         extension_settings.cfg.chara.push(tempCharaCfg);
//     } else {
//         console.debug('Character CFG error: No avatar name key could be found.');

//         // Don't save settings if something went wrong
//         return false;
//     }

//     updateSettings();

//     return true;
// }

// function setChatCfg(tempValue, setting) {
//     switch(setting) {
//         case settingType.guidance_scale:
//             chat_metadata[metadataKeys.guidance_scale] = tempValue;
//             break;
//         case settingType.negative_prompt:
//             chat_metadata[metadataKeys.negative_prompt] = tempValue;
//             break;
//         case settingType.positive_prompt:
//             chat_metadata[metadataKeys.positive_prompt] = tempValue;
//             break;
//         default:
//             return false;
//     }

//     saveMetadataDebounced();

//     return true;
// }

// // TODO: Only change CFG when character is selected
// function onCfgMenuItemClick() {
//     if (selected_group || this_chid) {
//         //show CFG config if it's hidden
//         if ($('#cfgConfig').css('display') !== 'flex') {
//             $('#cfgConfig').addClass('resizing');
//             $('#cfgConfig').css('display', 'flex');
//             $('#cfgConfig').css('opacity', 0.0);
//             $('#cfgConfig').transition({
//                 opacity: 1.0,
//                 duration: animation_duration,
//             }, async function () {
//                 await delay(50);
//                 $('#cfgConfig').removeClass('resizing');
//             });

//             //auto-open the main AN inline drawer
//             if ($('#CFGBlockToggle')
//                 .siblings('.inline-drawer-content')
//                 .css('display') !== 'block') {
//                 $('#floatingPrompt').addClass('resizing');
//                 $('#CFGBlockToggle').click();
//             }
//         } else {
//             //hide AN if it's already displayed
//             $('#cfgConfig').addClass('resizing');
//             $('#cfgConfig').transition({
//                 opacity: 0.0,
//                 duration: animation_duration,
//             },
//             async function () {
//                 await delay(50);
//                 $('#cfgConfig').removeClass('resizing');
//             });
//             setTimeout(function () {
//                 $('#cfgConfig').hide();
//             }, animation_duration);

//         }
//         //duplicate options menu close handler from script.js
//         //because this listener takes priority
//         $('#options').stop().fadeOut(animation_duration);
//     } else {
//         toastr.warning('Select a character before trying to configure CFG', '', { timeOut: 2000 });
//     }
// }

// async function onChatChanged() {
//     loadSettings();
//     await modifyCharaHtml();
// }

// // Rearrange the panel if a group chat is present
// async function modifyCharaHtml() {
//     if (selected_group) {
//         $('#chara_cfg_container').hide();
//         $('#groupchat_cfg_use_chara_container').show();
//     } else {
//         $('#chara_cfg_container').show();
//         $('#groupchat_cfg_use_chara_container').hide();
//         // TODO: Remove chat checkbox here
//     }
// }

// // Reloads chat-specific settings
// function loadSettings() {
//     // Set chat CFG if it exists
//     $('#chat_cfg_guidance_scale').val(chat_metadata[metadataKeys.guidance_scale] ?? 1.0.toFixed(2));
//     $('#chat_cfg_guidance_scale_counter').val(chat_metadata[metadataKeys.guidance_scale]?.toFixed(2) ?? 1.0.toFixed(2));
//     $('#chat_cfg_negative_prompt').val(chat_metadata[metadataKeys.negative_prompt] ?? '');
//     $('#chat_cfg_positive_prompt').val(chat_metadata[metadataKeys.positive_prompt] ?? '');
//     $('#groupchat_cfg_use_chara').prop('checked', chat_metadata[metadataKeys.groupchat_individual_chars] ?? false);
//     if (chat_metadata[metadataKeys.prompt_combine]?.length > 0) {
//         chat_metadata[metadataKeys.prompt_combine].forEach((element) => {
//             $(`input[name="cfg_prompt_combine"][value="${element}"]`)
//                 .prop('checked', true);
//         });
//     }

//     // Display the negative separator in quotes if not quoted already
//     let promptSeparatorDisplay = [];
//     const promptSeparator = chat_metadata[metadataKeys.prompt_separator];
//     if (promptSeparator) {
//         promptSeparatorDisplay.push(promptSeparator);
//         if (!promptSeparator.startsWith('"')) {
//             promptSeparatorDisplay.unshift('"');
//         }

//         if (!promptSeparator.endsWith('"')) {
//             promptSeparatorDisplay.push('"');
//         }
//     }

//     $('#cfg_prompt_separator').val(promptSeparatorDisplay.length === 0 ? '' : promptSeparatorDisplay.join(''));

//     $('#cfg_prompt_insertion_depth').val(chat_metadata[metadataKeys.prompt_insertion_depth] ?? 1);

//     // Set character CFG if it exists
//     if (!selected_group) {
//         const charaCfg = extension_settings.cfg.chara.find((e) => e.name === getCharaFilename());
//         $('#chara_cfg_guidance_scale').val(charaCfg?.guidance_scale ?? 1.00);
//         $('#chara_cfg_guidance_scale_counter').val(charaCfg?.guidance_scale?.toFixed(2) ?? 1.0.toFixed(2));
//         $('#chara_cfg_negative_prompt').val(charaCfg?.negative_prompt ?? '');
//         $('#chara_cfg_positive_prompt').val(charaCfg?.positive_prompt ?? '');
//     }
// }

// // Load initial extension settings
// async function initialLoadSettings() {
//     // Create the settings if they don't exist
//     extension_settings[extensionName] = extension_settings[extensionName] || {};
//     if (Object.keys(extension_settings[extensionName]).length === 0) {
//         Object.assign(extension_settings[extensionName], defaultSettings);
//         saveSettingsDebounced();
//     }

//     // Set global CFG values on load
//     $('#global_cfg_guidance_scale').val(extension_settings.cfg.global.guidance_scale);
//     $('#global_cfg_guidance_scale_counter').val(extension_settings.cfg.global.guidance_scale.toFixed(2));
//     $('#global_cfg_negative_prompt').val(extension_settings.cfg.global.negative_prompt);
//     $('#global_cfg_positive_prompt').val(extension_settings.cfg.global.positive_prompt);
// }

// function migrateSettings() {
//     let performSettingsSave = false;
//     let performMetaSave = false;

//     if (power_user.guidance_scale) {
//         extension_settings.cfg.global.guidance_scale = power_user.guidance_scale;
//         delete power_user['guidance_scale'];
//         performSettingsSave = true;
//     }

//     if (power_user.negative_prompt) {
//         extension_settings.cfg.global.negative_prompt = power_user.negative_prompt;
//         delete power_user['negative_prompt'];
//         performSettingsSave = true;
//     }

//     if (chat_metadata['cfg_negative_combine']) {
//         chat_metadata[metadataKeys.prompt_combine] = chat_metadata['cfg_negative_combine'];
//         chat_metadata['cfg_negative_combine'] = undefined;
//         performMetaSave = true;
//     }

//     if (chat_metadata['cfg_negative_insertion_depth']) {
//         chat_metadata[metadataKeys.prompt_insertion_depth] = chat_metadata['cfg_negative_insertion_depth'];
//         chat_metadata['cfg_negative_insertion_depth'] = undefined;
//         performMetaSave = true;
//     }

//     if (chat_metadata['cfg_negative_separator']) {
//         chat_metadata[metadataKeys.prompt_separator] = chat_metadata['cfg_negative_separator'];
//         chat_metadata['cfg_negative_separator'] = undefined;
//         performMetaSave = true;
//     }

//     if (performSettingsSave) {
//         saveSettingsDebounced();
//     }

//     if (performMetaSave) {
//         saveMetadataDebounced();
//     }
// }

// // This function is called when the extension is loaded
// export function initCfg() {
//     $('#CFGClose').on('click', function () {
//         $('#cfgConfig').transition({
//             opacity: 0,
//             duration: animation_duration,
//             easing: 'ease-in-out',
//         });
//         setTimeout(function () { $('#cfgConfig').hide(); }, animation_duration);
//     });

//     $('#chat_cfg_guidance_scale').on('input', function() {
//         const numberValue = Number($(this).val());
//         const success = setChatCfg(numberValue, settingType.guidance_scale);
//         if (success) {
//             $('#chat_cfg_guidance_scale_counter').val(numberValue.toFixed(2));
//         }
//     });

//     $('#chat_cfg_negative_prompt').on('input', function() {
//         setChatCfg($(this).val(), settingType.negative_prompt);
//     });

//     $('#chat_cfg_positive_prompt').on('input', function() {
//         setChatCfg($(this).val(), settingType.positive_prompt);
//     });

//     $('#chara_cfg_guidance_scale').on('input', function() {
//         const value = $(this).val();
//         const success = setCharCfg(value, settingType.guidance_scale);
//         if (success) {
//             $('#chara_cfg_guidance_scale_counter').val(Number(value).toFixed(2));
//         }
//     });

//     $('#chara_cfg_negative_prompt').on('input', function() {
//         setCharCfg($(this).val(), settingType.negative_prompt);
//     });

//     $('#chara_cfg_positive_prompt').on('input', function() {
//         setCharCfg($(this).val(), settingType.positive_prompt);
//     });

//     $('#global_cfg_guidance_scale').on('input', function() {
//         extension_settings.cfg.global.guidance_scale = Number($(this).val());
//         $('#global_cfg_guidance_scale_counter').val(extension_settings.cfg.global.guidance_scale.toFixed(2));
//         saveSettingsDebounced();
//     });

//     $('#global_cfg_negative_prompt').on('input', function() {
//         extension_settings.cfg.global.negative_prompt = $(this).val();
//         saveSettingsDebounced();
//     });

//     $('#global_cfg_positive_prompt').on('input', function() {
//         extension_settings.cfg.global.positive_prompt = $(this).val();
//         saveSettingsDebounced();
//     });

//     $('input[name="cfg_prompt_combine"]').on('input', function() {
//         const values = $('#cfgConfig').find('input[name="cfg_prompt_combine"]')
//             .filter(':checked')
//             .map(function() { return Number($(this).val()); })
//             .get()
//             .filter((e) => !Number.isNaN(e)) || [];

//         chat_metadata[metadataKeys.prompt_combine] = values;
//         saveMetadataDebounced();
//     });

//     $('#cfg_prompt_insertion_depth').on('input', function() {
//         chat_metadata[metadataKeys.prompt_insertion_depth] = Number($(this).val());
//         saveMetadataDebounced();
//     });

//     $('#cfg_prompt_separator').on('input', function() {
//         chat_metadata[metadataKeys.prompt_separator] = $(this).val();
//         saveMetadataDebounced();
//     });

//     $('#groupchat_cfg_use_chara').on('input', function() {
//         const checked = !!$(this).prop('checked');
//         chat_metadata[metadataKeys.groupchat_individual_chars] = checked;

//         if (checked) {
//             toastr.info('You can edit character CFG values in their respective character chats.');
//         }

//         saveMetadataDebounced();
//     });

//     initialLoadSettings();

//     if (extension_settings.cfg) {
//         migrateSettings();
//     }

//     $('#option_toggle_CFG').on('click', onCfgMenuItemClick);

//     // Hook events
//     eventSource.on(event_types.CHAT_CHANGED, async () => {
//         await onChatChanged();
//     });
// }

export const cfgType = {
    chat: 0,
    chara: 1,
    global: 2,
};

export const metadataKeys = {
    guidance_scale: 'cfg_guidance_scale',
    negative_prompt: 'cfg_negative_prompt',
    positive_prompt: 'cfg_positive_prompt',
    prompt_combine: 'cfg_prompt_combine',
    groupchat_individual_chars: 'cfg_groupchat_individual_chars',
    prompt_insertion_depth: 'cfg_prompt_insertion_depth',
    prompt_separator: 'cfg_prompt_separator',
};

// Gets the CFG guidance scale
// If the guidance scale is 1, ignore the CFG prompt(s) since it won't be used anyways
export function getGuidanceScale() {
    if (!extension_settings.cfg) {
        console.warn('CFG extension is not enabled. Skipping CFG guidance.');
        return;
    }

    const charaCfg = extension_settings.cfg.chara?.find((e) => e.name === getCharaFilename(this_chid));
    const chatGuidanceScale = chat_metadata[metadataKeys.guidance_scale];
    const groupchatCharOverride = chat_metadata[metadataKeys.groupchat_individual_chars] ?? false;

    if (chatGuidanceScale && chatGuidanceScale !== 1 && !groupchatCharOverride) {
        return {
            type: cfgType.chat,
            value: chatGuidanceScale,
        };
    }

    if ((!selected_group && charaCfg || groupchatCharOverride) && charaCfg?.guidance_scale !== 1) {
        return {
            type: cfgType.chara,
            value: charaCfg.guidance_scale,
        };
    }

    if (extension_settings.cfg.global && extension_settings.cfg.global?.guidance_scale !== 1) {
        return {
            type: cfgType.global,
            value: extension_settings.cfg.global.guidance_scale,
        };
    }
}

/**
 * Gets the CFG prompt separator.
 * @returns {string} The CFG prompt separator
 */
function getCustomSeparator() {
    const defaultSeparator = '\n';

    try {
        if (chat_metadata[metadataKeys.prompt_separator]) {
            return JSON.parse(chat_metadata[metadataKeys.prompt_separator]);
        }

        return defaultSeparator;
    } catch {
        console.warn('Invalid JSON detected for prompt separator. Using default separator.');
        return defaultSeparator;
    }
}

// Gets the CFG prompt
export function getCfgPrompt(guidanceScale, isNegative) {
    let splitCfgPrompt = [];

    const cfgPromptCombine = chat_metadata[metadataKeys.prompt_combine] ?? [];
    if (guidanceScale.type === cfgType.chat || cfgPromptCombine.includes(cfgType.chat)) {
        splitCfgPrompt.unshift(
            substituteParams(
                chat_metadata[isNegative ? metadataKeys.negative_prompt : metadataKeys.positive_prompt],
            ),
        );
    }

    const charaCfg = extension_settings.cfg.chara?.find((e) => e.name === getCharaFilename(this_chid));
    if (guidanceScale.type === cfgType.chara || cfgPromptCombine.includes(cfgType.chara)) {
        splitCfgPrompt.unshift(
            substituteParams(
                isNegative ? charaCfg.negative_prompt : charaCfg.positive_prompt,
            ),
        );
    }

    if (guidanceScale.type === cfgType.global || cfgPromptCombine.includes(cfgType.global)) {
        splitCfgPrompt.unshift(
            substituteParams(
                isNegative ? extension_settings.cfg.global.negative_prompt : extension_settings.cfg.global.positive_prompt,
            ),
        );
    }

    const customSeparator = getCustomSeparator();
    const combinedCfgPrompt = splitCfgPrompt.filter((e) => e.length > 0).join(customSeparator);
    const insertionDepth = chat_metadata[metadataKeys.prompt_insertion_depth] ?? 1;
    console.log(`Setting CFG with guidance scale: ${guidanceScale.value}, negatives: ${combinedCfgPrompt}`);

    return {
        value: combinedCfgPrompt,
        depth: insertionDepth,
    };
}
